package com.wfm.lock.reentrantlock;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ProducerConsumerQueue<T> {
    private final Queue<T> queue; // 存储队列
    private final int capacity;   // 队列的最大容量
    private final Lock lock = new ReentrantLock(); // 锁
    private final Condition notEmpty = lock.newCondition(); // 队列非空条件  消费者队列
    private final Condition notFull = lock.newCondition();  // 队列未满条件 生产者队列

    public ProducerConsumerQueue(int capacity) {
        this.queue = new LinkedList<>();
        this.capacity = capacity;
    }

    /**
     * 生产者方法：向队列中添加元素
     */
    public void produce(T item) throws InterruptedException {
        lock.lock();
        try {
            // 如果队列已满，等待
            while (queue.size() == capacity) {
                System.out.println("队列已满，生产者等待...");
                notFull.await();
            }
            // 添加元素到队列
            queue.add(item);
            System.out.println("生产：" + item);
            // 通知消费者队列非空
            notEmpty.signalAll();
        } finally {
            lock.unlock();
        }
    }

    /**
     * 消费者方法：从队列中取出元素
     */
    public T consume() throws InterruptedException {
        lock.lock();
        try {
            // 如果队列为空，等待
            while (queue.isEmpty()) {
                System.out.println("队列为空，消费者等待...");
                notEmpty.await();
            }
            // 取出队列头部元素
            T item = queue.poll();
            System.out.println("消费：" + item);
            // 通知生产者队列未满
            notFull.signalAll();
            return item;
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        ProducerConsumerQueue<Integer> queue = new ProducerConsumerQueue<>(5);

        // 创建多个生产者线程
        Runnable producerTask = () -> {
            try {
                for (int i = 0; i < 10; i++) {
                    queue.produce(i);
                    Thread.sleep(100); // 模拟生产延迟
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        };

        // 创建多个消费者线程
        Runnable consumerTask = () -> {
            try {
                for (int i = 0; i < 10; i++) {
                    queue.consume();
                    Thread.sleep(150); // 模拟消费延迟
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        };

        // 启动多个生产者和消费者线程
        Thread producer1 = new Thread(producerTask, "Producer-1");
        Thread producer2 = new Thread(producerTask, "Producer-2");
        Thread consumer1 = new Thread(consumerTask, "Consumer-1");
        Thread consumer2 = new Thread(consumerTask, "Consumer-2");

        producer1.start();
        producer2.start();
        consumer1.start();
        consumer2.start();
    }
}